<?php

namespace Trois\Process;

use App\HttpController\Open\Mini;
use EasySwoole\Component\Singleton;
use EasySwoole\Component\WaitGroup;
use EasySwoole\EasySwoole\Logger;
use Swoole\Process;
use Trois\Lib\Help;

class CheckMiniProcess extends BaseProcess
{
    use Singleton;

    private string $url = 'http://yiye.jiaoyueyan.cn/mapp.php?app_id=';

    private string $checkCurrentCache = 'system:mini-current-check';

    private int $nums = 100;


    private function __construct()
    {
        $this->processName = "CheckMiniProcess";
        $this->processGroup = "CheckMiniProcess";

        parent::__construct();

    }

    protected function start()
    {
        Logger::getInstance()->info('start 方法');

        while(1) {

            Logger::getInstance()->info("开始处理 CheckMiniProcess");

            $checkCurrent = Help::redisPoolStringInvoke($this->checkCurrentCache);

//            dd($checkCurrent);

            $checkCurrent = $checkCurrent ?: 0;

            $res = \EasySwoole\RedisPool\RedisPool::invoke(function (\EasySwoole\Redis\Redis $redis) use ($checkCurrent) {

                return $redis->ZRANGE(Mini::$key, $checkCurrent, ($checkCurrent + $this->nums));

            });

            $res = $res ?? [];

//            dd($res);

            $checkCurrent = $checkCurrent + $this->nums + 1;

            if (!$res || count($res) < ($this->nums + 1)) {
                $checkCurrent = 0;
            }

//            dd($checkCurrent);

            Help::redisPoolStringInvoke($this->checkCurrentCache, $checkCurrent, 86400 * 365);

            $handles = [];

            $wait = new WaitGroup();

            foreach ($res as $re) {

//            \co::sleep(0.1);

                $_re = explode('_', $re);

                $status = $_re[1];

                if ($status != 1) {
                    continue;
                }

                $wait->add();

                go(function () use ($wait, $re, &$handles) {

                    $_re = explode('_', $re);

                    $app_id = $_re[0];

                    $handles[$re] = Help::curl('get', ($this->url . $app_id), [], [], 1);
                    $wait->done();

                });

            }

//        dd($handles);
            $wait->wait();

            Logger::getInstance()->info("CheckMiniStatueCrontab 返回成功：" . count($handles));

            $fail = [];

            $remove = [];

            foreach ($handles as $re => $response) {

                if ($response['response_code'] === 0) {

                    $_re = explode('_', $re);

                    if ($response['response_content']['state'] != 1) {
                        $_re[1] = $response['response_content']['error_code'];
                        $_re[3] = date('m-d-H:i:s');

                        $fail[] = 99;
                        $fail[] = implode('_', $_re);

                        $remove[] = $re;

                    }
                }

            }

            Logger::getInstance()->info("CheckMiniStatueCrontab 失效小程序：." . count($fail) / 2);

            \EasySwoole\RedisPool\RedisPool::invoke(function (\EasySwoole\Redis\Redis $redis) use ($fail) {
                $fail && $redis->zAdd(Mini::$key, ...$fail);
            });


            \EasySwoole\RedisPool\RedisPool::invoke(function (\EasySwoole\Redis\Redis $redis) use ($remove) {
                $remove && $redis->zRem(Mini::$key, ...$remove);
            });

            // 休息1秒
            \Co::sleep(3);

        }

    }


    protected function onPipeReadable(Process $process)
    {
        // 当主进程对子进程发送消息的时候 会触发
        $processName = $this->getProcessName(); // 获取 注册进程名称
        $processPid = $this->getPid();  // 获取 当前进程 Pid

        $recvMsgFromMain = json_decode($process->read(), true); // 用于获取主进程给当前进程发送的消息

        $action = isset($recvMsgFromMain['action']) ? $recvMsgFromMain['action'] : '';
        $param = isset($recvMsgFromMain['param']) ? $recvMsgFromMain['param'] : [];

        Logger::getInstance()->info('### ' . $processName . ':' . $processPid . ' 收到主进程发送的消息: ' . json_encode($recvMsgFromMain, JSON_UNESCAPED_UNICODE) . ' ###');

        if (method_exists($this, $action)) {
            return call_user_func_array([$this, $action], [$param]);
        } else {
            Logger::getInstance()->info('process 方法不存在');
        }

    }

}